Skip to content

feat(napi): add RwSite.listSections()#569

Merged
yumike merged 1 commit into
mainfrom
napi-list-sections
Jun 23, 2026
Merged

feat(napi): add RwSite.listSections()#569
yumike merged 1 commit into
mainfrom
napi-list-sections

Conversation

@yumike

@yumike yumike commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Implements #567 — exposes the full section hierarchy through the @rwdocs/core napi addon in one call.

What

  • RwSite.listSections()SectionEntry[], where SectionEntry = { sectionRef, path, ancestors }. Returns every section flat — canonical ref (kind:namespace/name), scope path ("" = root), and full nearest-first ancestry (root last). Removes the N+1 getNavigation() descent a consumer otherwise needs, since nested sections deliberately appear as childless leaves in their parent scope. sectionRef is named to match PageMeta.sectionRef.

Why it's cheap

Purely additive over the already-flat SiteState.sections map — no new internal state, no schema change, no behavioural change to existing methods. Ancestry reuses the find_parent_section prefix-walk; the output is sorted by scope path.

Scope trims (per review)

The issue originally proposed two extras that the consumer turned out not to need, so they're left out to avoid shipping unused public surface — both trivially re-addable later:

  • resolveSection(path) — dropped; the consumer keys off listSections().path and stored canonical refs. The internal Site::section_location is untouched (still used by renderPage); its custom-root-namespace correctness is retained and tested.
  • SectionEntry.title — dropped; v1 rows are grouped/labeled by entity + page path, not section title. The section root page's title is already in the loaded snapshot, so it's free to re-add if a UI wants friendlier labels.

Tests

  • rw-site unit tests: flat listing + deterministic sort, ancestry (nearest-first / root-last, non-section intermediate skip), explicit root kind, custom root namespace.
  • @rwdocs/core JS integration test: createSite → listSections against a fixture docs tree.

🤖 Generated with Claude Code

@yumike

yumike commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

YAGNI follow-up after wiring the consumer side: we ended up not using resolveSection. The doc-comment inbox bridges annotation claim paths by matching against listSections().path (with trivial slash normalization), and the comment write path stores document_id's already-canonical sectionRef verbatim — so nothing calls a path→section resolver.

listSections() is the load-bearing primitive and we'd like to keep it exactly as is. resolveSection would land as unused public API surface, so I'd suggest dropping it from this PR (the resolve_section method + SectionLocationResponse + its index.d.ts entry + the two JS resolveSection tests) and re-adding only if a real consumer appears — it's a thin wrapper over the existing section_location, trivial to restore.

Note this loses nothing on correctness:

  • The root-namespace fix we cared about is consumer-side (the write path keys off document_id's canonical ref); the Rust section_location custom-namespace test can stay regardless.
  • section_location itself is untouched (still used internally by renderPage); we're only declining to expose it on the napi surface for now.

Net: keep listSections(), drop resolveSection.

@yumike yumike force-pushed the napi-list-sections branch from c7cb753 to 43a150a Compare June 23, 2026 03:35
@yumike yumike changed the title feat(napi): add RwSite.listSections() and resolveSection() feat(napi): add RwSite.listSections() Jun 23, 2026
@yumike yumike force-pushed the napi-list-sections branch from 43a150a to ebcfd01 Compare June 23, 2026 03:48
@yumike

yumike commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

One more YAGNI trim on the same theme: on the consumer side we also don't display section titles in v1 — rows are grouped by owning entity and labeled by entity + page path. So SectionEntry.title would ship unused as well.

Suggest dropping title from SectionEntry too, leaving { ref, path, ancestors } — which is everything the consumer's roll-up needs (ref = key + claim match, ancestors = nearest-entity roll-up, path = scope-relative deep-link). title is free to re-add later (the section root page's title is already in the loaded snapshot) if a UI wants friendlier section labels.

Net for this PR: keep listSections() returning { ref, path, ancestors }; drop resolveSection and SectionEntry.title.

@yumike yumike force-pushed the napi-list-sections branch from ebcfd01 to 4842a7e Compare June 23, 2026 04:05
Expose the full section hierarchy through the @rwdocs/core napi addon in one
call, so a host (e.g. a Backstage doc-comment inbox) no longer needs N+1
getNavigation() calls to walk nested sections — which deliberately appear as
childless leaves in their parent scope.

listSections() returns every section flat as { sectionRef, path, ancestors }:
canonical ref (kind:namespace/name), scope path, and full nearest-first
ancestry (root last). Backed by SiteState::list_sections over the already-flat
Sections map; ancestry via a prefix-walk mirroring find_parent_section. Output
sorted by scope path.

Adds SectionEntry (rw-site) and SectionEntryResponse (rw-napi), regenerates the
NAPI-RS index.d.ts, and covers the behavior with rw-site unit tests (ancestry
incl. non-section intermediates, custom root namespace) and a @rwdocs/core JS
integration test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yumike yumike force-pushed the napi-list-sections branch from 4842a7e to c345391 Compare June 23, 2026 04:48
@yumike yumike merged commit 0eb42cf into main Jun 23, 2026
18 checks passed
@yumike yumike deleted the napi-list-sections branch June 23, 2026 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant